/*
 *  Project: 
 *  Description: 
 *  Author: 
 *  License: 
 */

;(function(window, document, undefined) {
	var moduleName = 'coreTpl',
	ie6 = window.VBArray && !window.XMLHttpRequest;
	window[moduleName] = {
		_data: {},
		_tpls: {},
		guid: function() {
			return "NTGUID__" + (this.guid._counter++).toString(36)
		},
		dguid: function() {
			return "NDTGUID__" + (this.dguid._counter++).toString(36)
		},
		_load: function(url, callback) {
			var that = this,
			_script = document.createElement("script");
			_script.type = "text/javascript";
			if (_script.readyState) {
				_script.onreadystatechange = function() {
					if (ie6 && !this.getAttribute("initialized")) {
						document.getElementsByTagName("head")[0].appendChild(_script);
						this.setAttribute("initialized", true)
					}
					if (this.readyState == "loaded" || this.readyState == "complete") {
						this.onreadystatechange = null;
						callback && callback.call(that)
					}
				};
				_script.src = url; ! ie6 && document.getElementsByTagName("head")[0].appendChild(_script)
			} else {
				_script.src = url;
				_script.onload = function() {
					callback && callback.call(that)
				};
				document.getElementsByTagName("head")[0].appendChild(_script)
			}
			return this
		},
		_fixcss: function(css) {
			var style = document.getElementById("coretpl_css");
			if (!style) {
				style = document.createElement("style");
				style.setAttribute("type", "text/css");
				style.setAttribute("id", "coretpl_css");
				document.getElementsByTagName("head")[0].appendChild(style)
			}
			if (style.styleSheet) {
				style.styleSheet.cssText += css
			} else {
				style.appendChild(document.createTextNode(css))
			}
		},
		get: function(path, data, callback) {
			var version = typeof Loader !== 'undefined' && Loader.c ? Loader.c: "",
			that = this,
      key,
			cache;
			path = 'tpls/' + path + '.js';
			cache = that._tpls;
      key = path.replace(/^tpls/,'');
      path = Loader.s + Loader.p + path;
			if (typeof cache[key] === 'object' && typeof cache[key].main === 'function') {
				typeof callback === 'function' && callback.call(that, cache[key].main(data))
			} else {
				this._load(path + '?' + version,
				function() {
					typeof callback === 'function' && typeof cache[key] === 'object' && typeof cache[key].main === 'function' && callback.call(that, cache[key].main(data))
				})
			}
			return this
		}
	};
	window[moduleName].render = function(html, data, callback) {
		var path = Math.random(),
		that = this,
		cache = that._tpls;
		var renderTools = {
			trim: function(str) {
				return str.trim()
			},
			split: function(str, separator, limit) {
				return str.split(separator, limit)
			},
			precompile: function(tpl) {
				if (!tpl) return false;
				var tplTemp,
				tplList = {},
				compileList = {};
				var tplExp = /<template(.*name=['"]([^'"]+)*)?\b[^>]*>([^<]*(?:(?!<\/template>)<[^<]*)*)<\/template>/igm;
				while (tplTemp = tplExp.exec(tpl)) tplTemp[2] && (tplList[tplTemp[2]] = tplTemp[3]);
				tplList["main"] = tplList["main"] || tpl;
				this.compile(tplList, compileList);
				return compileList
			},
			compile: function(tplList, compileList) {
				var that = this;
				if (typeof tplList !== 'object') return false;
				for (var tplname in tplList) {
					var html = tplList[tplname];
					if (!html) continue;
					var jsExp = /<script\b[^>]*>([^<]*(?:(?!<\/script>)<[^<]*)*)<\/script>/igm,
					cssExp = /<style\b[^>]*>([^<]*(?:(?!<\/style>)<[^<]*)*)<\/style>/igm;
					var jscode = '',
					csscode = '';
					html = html.replace(cssExp,
					function($, $1) {
						csscode += "\r\n" + $1;
						return ""
					}).replace(jsExp,
					function($, $1) {
						jscode += "\r\n" + $1;
						return ""
					});
					jscode = that.trim(jscode);
					csscode = that.trim(csscode);
					html = that.trim(html);
					if (csscode) {
						csscode = csscode.replace(/'/g, '\\\'');
						csscode = '    css += \'' + csscode.replace(/\/\*(.|\n)*?\*\//ig, '').replace(/\r?\n/ig, '').replace(/([a-zA-Z0-9_\-#*\.:\s,\(\)'"<>=]*)(\{)/ig,
						function(a, b, c) {
							b = that.trim(b);
							if (b === '') {
								return '#\' + guid + \'' + c
							} else {
								var _b = b.split(',');
								for (var i = 0; i < _b.length; i++) {
									_b[i] = that.trim(_b[i]);
									_b[i] = '\';\r\n    css += \'#\' + guid + \'' + (_b[i].indexOf(':') === 0 ? '': ' ') + _b[i]
								}
								return _b.join(',') + c
							}
						});
						csscode += '\';'
					}
					if (jscode) {
						var _jscode;
						_jscode = that.split(jscode, /\r?\n/g);
						for (var i = 0; i < _jscode.length; i++) {
							if (!_jscode[i]) continue;
							_jscode[i] = '    template.push(\'' + _jscode[i].replace(/\\/g, '\\\\').replace(/\'/g, '\\\'').replace(/\r\n/g, '\n').replace(/\n/g, '\\n').replace(/\$SUBROOT/g, '$(\\\'#\'+ guid + dguid + \'\\\')').replace(/require\(([^\)]*)\)/ig,
							function(a, b) {
								var _b = (b || '').split(',');
								_b.map(function(value, index) {
									_b[index] = that.trim(_b[index])
								});
								return '$TPLS[' + _b[0] + '](' + (_b.length > 1 ? _b[1] : '$DATA') + ', "\'+ guid +\'")'
							}) + '\\n\');\n'
						}
						jscode = _jscode.join('')
					}
					if (html) {
						var _html;
						_html = that.split(html, /(<\?[\s\S]*?\?>)/g);
						for (var i = 0; i < _html.length; i++) {
							if (!_html[i]) continue;
							if (new RegExp('<\\?[\\s\\S]*?\\?>', 'igm').test(_html[i])) {
								_html[i] = _html[i].replace(/<\?([\s\S]*?)\?>/igm, '$1');
								_html[i] = _html[i].replace(/@([a-zA-Z\$_]+)/igm, '$DATA.$1');
								_html[i] = _html[i].replace(/print\((.*?)\);/igm, '    template.push(($1) || \'\');\n');
								if (_html[i].indexOf('=') === 0) {
									_html[i] = '    template.push(((' + _html[i].substring(1) + ') == null ? \'\' : (' + _html[i].substring(1) + ')));'
								}
							} else {
								_html[i] = '\n    template.push(\'' + _html[i].replace(/\\/g, '\\\\').replace(/\'/g, '\\\'').replace(/\r\n/g, '\n').replace(/\n/g, '\\n') + '\');\n'
							}
						}
						html = _html.join('');
						html = html.replace(/\$ROOT/igm, '\'+ guid +\'');
						html = html.replace(/\$SUBROOT/igm, '\'+ guid + dguid +\'')
					}
					compileList[tplname] = {
						css: csscode,
						js: jscode,
						html: html
					}
				}
			},
			templete: function(path, tpl) {
				var html = "",
				tpls = [];
				for (var i in tpl) {
					var _html = "";
					_html += '  "' + i + '": function($DATA, guid){\n';
					_html += "    var css = '', dguid = N.dguid();\n";
					_html += "    var template = {\n";
					_html += "      init: function(){\n";
					_html += "        this.v8 = !!''.trim;\n";
					_html += "        this.result = this.v8 ? '' : [];\n";
					_html += "      },\n";
					_html += "      push: function(str){\n";
					_html += "        this.v8 ? (this.result += str) : this.result.push(str);\n";
					_html += "      },\n";
					_html += "      html: function(){\n";
					_html += "        return this.v8 ? this.result : this.result.join('');\n";
					_html += "      }\n";
					_html += "    };\n";
					_html += "    guid = guid || N.guid();\n";
					_html += "    template.init();\n";
					if (tpl[i].css) {
						_html += tpl[i].css + "\n";
						_html += "    if(N.ie6){\n";
						_html += "      N._fixcss(css);\n";
						_html += "    } else {\n";
						_html += "      template.push('<style>' + css + '</style>');\n";
						_html += "    }"
					}
					if (tpl[i].html) {
						_html += tpl[i].html
					}
					if (tpl[i].js) {
						_html += "    template.push('<script>');\n";
						_html += "    template.push('(function(window, document, undefined){\\n');\n";
						_html += "    template.push('  var $ROOT = $(\"#'+ guid +'\");\\n');\n";
						_html += "    template.push('  var $TPLS = coreTpl._tpls[\"\'+ PATH +\'\"];\\n');\n";
						_html += "    template.push('  var $DATA = coreTpl._data[\"\'+ dguid +\'\"];\\n');\n";
						_html += tpl[i].js;
						_html += "    template.push('})(window, document);\\n');\n";
						_html += "    template.push('delete coreTpl._data[\"\'+ dguid +\'\"];\\n');\n";
						_html += "    template.push('</script>\\n');\n"
					}
					_html += '    $DATA && (N._data[dguid] = $DATA);\n';
					_html += "    return template.html();\n";
					_html += '  }';
					tpls.push(_html)
				}
				html += "(function(N, undefined){\n";
				html += "  var PATH = '" + path + "';\n";
				html += "  if(!N || !N._tpls) return false;\n";
				html += "  N._tpls[PATH] = N._tpls[PATH] ||\n{\n";
				html += tpls.join(',\n');
				html += '\n};';
				html += "\n})(window.coreTpl);";
				return html
			}
		}; (new Function(renderTools.templete(path, renderTools.precompile(html))))();
		typeof callback === 'function' && typeof cache[path] === 'object' && typeof cache[path].main === 'function' && callback.call(that, cache[path].main(data));
		return that
	};
	window[moduleName].guid._counter = 1;
	window[moduleName].dguid._counter = 1;
} (window, document));
